package cn.christ.com.mobilesafe.common.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import java.lang.reflect.Method;
import java.util.Map;

import cn.christ.com.mobilesafe.MyApp;

/**
 * Created by Administrator on 2018/7/15.
 * 对SP的操作封装成了静态方法put(),get(),remove(),clear()等，put(),remove(),get(),clear()等
 * 上面类中使用的不是commit方法而是apply方法，为什么？找一下鸿洋大神的博客，发现：commit方法是同步的，
 * 并且我们很多时候的commit操作都是UI线程中，毕竟是IO操作，尽可能异步；所以我们使用apply进行替代，
 * apply异步的进行写入。这样就清楚了。上述类通过反射获取SP.Editor中的apply()方法，
 * 重命名为sApplyMethod，调用invoke方法来实现将数据传递给editor，然后editor提交，从而完成apply()封装。
 */

public class SPUtils {
    public static final String FILE_NAME = "share_data";
    private static SharedPreferences sp;

    static {
        Context context = MyApp.context;
        sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
    }

    /**
     * 保存数据的方法，我们需要拿到数据的具体类型，然后根据数据类型调用不同的保存方法
     */
    public static void put(String key, Object object) {
        SharedPreferences.Editor editor = sp.edit();
        if (object instanceof String) {
            editor.putString(key, (String) object);
        } else if (object instanceof Integer) {
            editor.putInt(key, (Integer) object);
        } else if (object instanceof Boolean) {
            editor.putBoolean(key, (Boolean) object);
        } else if (object instanceof Float) {
            editor.putFloat(key, (Float) object);
        } else if (object instanceof Long) {
            editor.putLong(key, (Long) object);
        } else {
            editor.putString(key, object.toString());
        }
        SharePreferencesCompat.apply(editor);
    }


    /**
     * 获取到sp的值
     *
     * @param key
     * @param defaultObject
     * @return
     */
    public static Object get(String key, Object defaultObject) {
        if (defaultObject instanceof String) {
            return sp.getString(key, (String) defaultObject);
        } else if (defaultObject instanceof Integer) {
            return sp.getInt(key, (int) defaultObject);
        } else if (defaultObject instanceof Boolean) {
            return sp.getBoolean(key, (boolean) defaultObject);
        } else if (defaultObject instanceof Float) {
            return sp.getFloat(key, (float) defaultObject);
        } else if (defaultObject instanceof Long) {
            return sp.getLong(key, (long) defaultObject);
        }
        return null;
    }

    /**
     * 移除sp的值
     *
     * @param key
     */
    public static void remove(String key) {
        SharedPreferences.Editor edit = sp.edit();
        edit.remove(key);
        SharePreferencesCompat.apply(edit);
    }


    /**
     * 移除所有的数据
     */
    public static void clear() {
        SharedPreferences.Editor edit = sp.edit();
        edit.clear();
        SharePreferencesCompat.apply(edit);
    }

    /**
     * 查询sp的值
     *
     * @param key
     * @return
     */
    public static boolean contains(String key) {
        return sp.contains(key);
    }

    /**
     * 获取所有的值
     *
     * @return
     */
    public static Map<String, ?> getAll() {
        return sp.getAll();
    }


    private static class SharePreferencesCompat {
        private static final Method sApplyMethod = findApplyMethod();

        /**
         * 反射查找apply的方法
         *
         * @return
         */
        @SuppressLint("LongLogTag")
        @SuppressWarnings({"unchecked", "rawtypes"})
        private static Method findApplyMethod() {
            try {
                Class clz = SharedPreferences.Editor.class;
                return clz.getMethod("apply");
            } catch (NoSuchMethodException e) {
                Log.d("NoSuchMethodException---SPUtils", e.getMessage());
            }
            return null;
        }


        public static void apply(SharedPreferences.Editor editor) {
            try {
                if (sApplyMethod != null) {
                    sApplyMethod.invoke(editor);
                    return;
                }
            } catch (Exception e) {
                Log.d("Exception", e.getMessage());
            }
            editor.commit();
        }
    }


}

